{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# Exploratory data analysis with labeled data\n",
    "Now that we have the labels for our data, we can do some initial EDA to see if there is something different between the hackers and the valid users.\n",
    "\n",
    "## Setup"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 1,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/html": [
       "<div>\n",
       "<style scoped>\n",
       "    .dataframe tbody tr th:only-of-type {\n",
       "        vertical-align: middle;\n",
       "    }\n",
       "\n",
       "    .dataframe tbody tr th {\n",
       "        vertical-align: top;\n",
       "    }\n",
       "\n",
       "    .dataframe thead th {\n",
       "        text-align: right;\n",
       "    }\n",
       "</style>\n",
       "<table border=\"1\" class=\"dataframe\">\n",
       "  <thead>\n",
       "    <tr style=\"text-align: right;\">\n",
       "      <th></th>\n",
       "      <th>start</th>\n",
       "      <th>end</th>\n",
       "      <th>source_ip</th>\n",
       "      <th>duration</th>\n",
       "      <th>start_floor</th>\n",
       "      <th>end_ceil</th>\n",
       "    </tr>\n",
       "  </thead>\n",
       "  <tbody>\n",
       "    <tr>\n",
       "      <th>0</th>\n",
       "      <td>2018-01-05 06:03:42.470259</td>\n",
       "      <td>2018-01-05 06:03:51.470259</td>\n",
       "      <td>170.9.4.108</td>\n",
       "      <td>00:00:09</td>\n",
       "      <td>2018-01-05 06:03:00</td>\n",
       "      <td>2018-01-05 06:04:00</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>1</th>\n",
       "      <td>2018-01-11 03:08:43.284085</td>\n",
       "      <td>2018-01-11 03:09:14.284085</td>\n",
       "      <td>27.255.30.3</td>\n",
       "      <td>00:00:31</td>\n",
       "      <td>2018-01-11 03:08:00</td>\n",
       "      <td>2018-01-11 03:10:00</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>2</th>\n",
       "      <td>2018-01-17 00:41:43.985324</td>\n",
       "      <td>2018-01-17 00:45:56.985324</td>\n",
       "      <td>226.98.192.152</td>\n",
       "      <td>00:04:13</td>\n",
       "      <td>2018-01-17 00:41:00</td>\n",
       "      <td>2018-01-17 00:46:00</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>3</th>\n",
       "      <td>2018-01-21 10:34:57.842776</td>\n",
       "      <td>2018-01-21 10:38:01.842776</td>\n",
       "      <td>102.178.107.171</td>\n",
       "      <td>00:03:04</td>\n",
       "      <td>2018-01-21 10:34:00</td>\n",
       "      <td>2018-01-21 10:39:00</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>4</th>\n",
       "      <td>2018-01-21 23:12:10.852725</td>\n",
       "      <td>2018-01-21 23:12:38.852725</td>\n",
       "      <td>48.172.61.152</td>\n",
       "      <td>00:00:28</td>\n",
       "      <td>2018-01-21 23:12:00</td>\n",
       "      <td>2018-01-21 23:13:00</td>\n",
       "    </tr>\n",
       "  </tbody>\n",
       "</table>\n",
       "</div>"
      ],
      "text/plain": [
       "                       start                        end        source_ip  \\\n",
       "0 2018-01-05 06:03:42.470259 2018-01-05 06:03:51.470259      170.9.4.108   \n",
       "1 2018-01-11 03:08:43.284085 2018-01-11 03:09:14.284085      27.255.30.3   \n",
       "2 2018-01-17 00:41:43.985324 2018-01-17 00:45:56.985324   226.98.192.152   \n",
       "3 2018-01-21 10:34:57.842776 2018-01-21 10:38:01.842776  102.178.107.171   \n",
       "4 2018-01-21 23:12:10.852725 2018-01-21 23:12:38.852725    48.172.61.152   \n",
       "\n",
       "  duration         start_floor            end_ceil  \n",
       "0 00:00:09 2018-01-05 06:03:00 2018-01-05 06:04:00  \n",
       "1 00:00:31 2018-01-11 03:08:00 2018-01-11 03:10:00  \n",
       "2 00:04:13 2018-01-17 00:41:00 2018-01-17 00:46:00  \n",
       "3 00:03:04 2018-01-21 10:34:00 2018-01-21 10:39:00  \n",
       "4 00:00:28 2018-01-21 23:12:00 2018-01-21 23:13:00  "
      ]
     },
     "execution_count": 1,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "%matplotlib inline\n",
    "import matplotlib.pyplot as plt\n",
    "import numpy as np\n",
    "import pandas as pd\n",
    "import seaborn as sns\n",
    "import sqlite3\n",
    "\n",
    "with sqlite3.connect('logs/logs.db') as conn:\n",
    "    logs_2018 = pd.read_sql(\n",
    "        'SELECT * FROM logs WHERE datetime BETWEEN \"2018-01-01\" AND \"2019-01-01\";', \n",
    "        conn, parse_dates=['datetime'], index_col='datetime'\n",
    "    )\n",
    "    hackers_2018 = pd.read_sql(\n",
    "        'SELECT * FROM attacks WHERE start BETWEEN \"2018-01-01\" AND \"2019-01-01\";', \n",
    "        conn, parse_dates=['start', 'end']\n",
    "    ).assign(\n",
    "        duration=lambda x: x.end - x.start, \n",
    "        start_floor=lambda x: x.start.dt.floor('min'),\n",
    "        end_ceil=lambda x: x.end.dt.ceil('min')\n",
    "    )\n",
    "hackers_2018.head()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "This function will tell us if the datetimes had hacker activity:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "metadata": {},
   "outputs": [],
   "source": [
    "def check_if_hacker(datetimes, hackers, resolution='1min'):\n",
    "    \"\"\"\n",
    "    Check whether a hacker attempted a log in during that time.\n",
    "    \n",
    "    Parameters:\n",
    "        - datetimes: The datetimes to check for hackers\n",
    "        - hackers: The dataframe indicating when the attacks started and stopped\n",
    "        - resolution: The granularity of the datetime. Default is 1 minute.\n",
    "        \n",
    "    Returns:\n",
    "        A pandas Series of booleans.\n",
    "    \"\"\"\n",
    "    date_ranges = hackers.apply(\n",
    "        lambda x: pd.date_range(x.start_floor, x.end_ceil, freq=resolution), \n",
    "        axis=1\n",
    "    )\n",
    "    dates = pd.Series()\n",
    "    for date_range in date_ranges:\n",
    "        dates = pd.concat([dates, date_range.to_series()])\n",
    "    return datetimes.isin(dates)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Let's label our data for Q1 so we can look for a separation boundary:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/html": [
       "<div>\n",
       "<style scoped>\n",
       "    .dataframe tbody tr th:only-of-type {\n",
       "        vertical-align: middle;\n",
       "    }\n",
       "\n",
       "    .dataframe tbody tr th {\n",
       "        vertical-align: top;\n",
       "    }\n",
       "\n",
       "    .dataframe thead th {\n",
       "        text-align: right;\n",
       "    }\n",
       "</style>\n",
       "<table border=\"1\" class=\"dataframe\">\n",
       "  <thead>\n",
       "    <tr style=\"text-align: right;\">\n",
       "      <th></th>\n",
       "      <th>usernames_with_failures</th>\n",
       "      <th>failures</th>\n",
       "      <th>flag</th>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>datetime</th>\n",
       "      <th></th>\n",
       "      <th></th>\n",
       "      <th></th>\n",
       "    </tr>\n",
       "  </thead>\n",
       "  <tbody>\n",
       "    <tr>\n",
       "      <th>2018-01-01 16:01:00</th>\n",
       "      <td>1</td>\n",
       "      <td>1</td>\n",
       "      <td>False</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>2018-01-01 16:02:00</th>\n",
       "      <td>0</td>\n",
       "      <td>0</td>\n",
       "      <td>False</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>2018-01-01 16:03:00</th>\n",
       "      <td>0</td>\n",
       "      <td>0</td>\n",
       "      <td>False</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>2018-01-01 16:04:00</th>\n",
       "      <td>0</td>\n",
       "      <td>0</td>\n",
       "      <td>False</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>2018-01-01 16:05:00</th>\n",
       "      <td>0</td>\n",
       "      <td>0</td>\n",
       "      <td>False</td>\n",
       "    </tr>\n",
       "  </tbody>\n",
       "</table>\n",
       "</div>"
      ],
      "text/plain": [
       "                     usernames_with_failures  failures   flag\n",
       "datetime                                                     \n",
       "2018-01-01 16:01:00                        1         1  False\n",
       "2018-01-01 16:02:00                        0         0  False\n",
       "2018-01-01 16:03:00                        0         0  False\n",
       "2018-01-01 16:04:00                        0         0  False\n",
       "2018-01-01 16:05:00                        0         0  False"
      ]
     },
     "execution_count": 3,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "users_with_failures = logs_2018['2018-Q1'].assign(\n",
    "    failures=lambda x:  1 - x.success\n",
    ").query('failures > 0').resample('1min').agg(\n",
    "    {'username':'nunique', 'failures': 'sum'}\n",
    ").dropna().rename(\n",
    "    columns={'username':'usernames_with_failures'}\n",
    ")\n",
    "labels = check_if_hacker(users_with_failures.reset_index().datetime, hackers_2018)\n",
    "users_with_failures['flag'] = labels[:users_with_failures.shape[0]].values\n",
    "users_with_failures.head()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Since we have the labels, we can draw a sample boundary that would separate most of the hackers from the valid users. Notice there is still at least one hacker in the valid users section of our separation:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "Text(0.5, 1.0, 'Usernames with failures on minute resolution')"
      ]
     },
     "execution_count": 4,
     "metadata": {},
     "output_type": "execute_result"
    },
    {
     "data": {
      "image/png": "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\n",
      "text/plain": [
       "<Figure size 432x288 with 1 Axes>"
      ]
     },
     "metadata": {
      "needs_background": "light"
     },
     "output_type": "display_data"
    }
   ],
   "source": [
    "ax = sns.scatterplot(\n",
    "    x=users_with_failures.usernames_with_failures, \n",
    "    y=users_with_failures.failures, \n",
    "    alpha=0.25,\n",
    "    hue=users_with_failures.flag\n",
    ")\n",
    "ax.plot([0, 8], [12, -4], 'r--', label='sample boundary')\n",
    "plt.ylim(-4, None)\n",
    "plt.legend()\n",
    "plt.title('Usernames with failures on minute resolution')"
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.7.2"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 2
}
